package net.wangds.auth.grant.comp;

import net.wangds.auth.grant.entity.GeneralGrantEntity;
import net.wangds.auth.grant.repo.rdbms.GrantJpaRepo;
import net.wangds.auth.module.*;
import net.wangds.auth.resource.repo.rdbms.ResourceJpaRepo;
import net.wangds.jpa.Sorts;
import net.wangds.jpa.comp.AbstractRemovedComp;
import net.wangds.log.helper.LogHelper;
import net.wangds.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class GeneralGrantComp extends AbstractRemovedComp<GeneralGrantEntity> {

    @Autowired
    private GrantJpaRepo mmRepoGrant;

    @Autowired
    private ResourceJpaRepo mmRepoRes;

    /**
     * 构造函数.
     *
     * @param repo 数据库操作对象.
     */
    public GeneralGrantComp(GrantJpaRepo repo) {
        super(repo);
    }

    public List<GeneralGrantEntity> listByOwnerId(String ownerId){
        return mmRepoGrant.findByOwnerId(ownerId);
    }

    public List<GeneralGrantEntity> listMenus(String ownerId){
        return mmRepoGrant.findByOwnerIdAndSchema(ownerId, ResourceSchemaEnum.MENU, Sorts.createTm_desc);
    }

    /**
     * 将资源权限授予指定用户.
     * @param res 资源.
     * @param ownerId 属主id.
     * @param ownerType 属主类型.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void grant(Resource res, String ownerId, GrantOwnerTypeEnum ownerType, int privilege){
        String resId = res.getId();
        GeneralGrantEntity entity = mmRepoGrant.findByOwnerIdAndResId(ownerId, resId).orElseGet(
                ()->{
                    GeneralGrantEntity grant = GeneralGrantEntity.of(ownerType, ownerId, res, privilege);
                    grant.setSchema(res.getSchema());
                    mmRepoGrant.save(grant);
                    return grant;
                }
        );
        entity.setAction(entity.getAction()|privilege);
        mmRepoGrant.saveAndFlush(entity);
    }

    /**
     * 撤销指定属主的资源授权.
     * @param res 资源.
     * @param ownerId 属主id.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void ungrant(Resource res, String ownerId, int privilege){

        String resId = res.getId();
        mmRepoGrant.findByOwnerIdAndResId(ownerId, resId).ifPresent(
                (grant)->{
                    grant.setAction(grant.getAction()&~privilege);
                    mmRepoGrant.saveAndFlush(grant);
                }
        );

    }

    /**
     * 将资源权限授予指定用户.
     * @param res 资源.
     * @param user 用户.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void grant(Resource res, User user, int privilege){
        grant(res, user.getId(), GrantOwnerTypeEnum.USER, privilege);
    }

    /**
     * 将资源授予指定的角色.
     * @param res 资源.
     * @param role 角色.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void grant(Resource res, Role role, int privilege){
        grant(res, role.getId(), GrantOwnerTypeEnum.ROLE, privilege);
    }

    /**
     * 将资源授予指定的职位.
     * @param res 资源.
     * @param job 职位.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void grant(Resource res, Job job, int privilege){
        grant(res, job.getId(), GrantOwnerTypeEnum.JOB, privilege);
    }

    /**
     * 将资源授予指定的账户.
     * @param res 资源.
     * @param account 账户.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void grant(Resource res, Account account, int privilege){
        grant(res, account.getId(), GrantOwnerTypeEnum.ACCOUNT, privilege);
    }

    /**
     * 撤销指定用户的资源授权.
     * @param res 资源.
     * @param user 用户.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void ungrant(Resource res, User user, int privilege){
        ungrant(res, user.getId(), privilege);
    }

    /**
     * 撤销指定角色的资源授权.
     * @param res 资源.
     * @param role 角色.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void ungrant(Resource res, Role role, int privilege){
        ungrant(res, role.getId(), privilege);
    }

    /**
     * 撤销指定职位的资源授权.
     * @param res 资源.
     * @param job 职位.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void ungrant(Resource res, Job job, int privilege){
        ungrant(res, job.getId(), privilege);
    }

    /**
     * 撤销指定账户的资源授权.
     * @param res 资源.
     * @param account 账户.
     * @param privilege 权限.
     * @see PrivilegeActionEnum
     */
    public void ungrant(Resource res, Account account, int privilege){
        ungrant(res, account.getId(), privilege);
    }


    public List<GeneralGrantEntity> findByOwnerIdAndSchema(String ownerId, ResourceSchemaEnum schema) {
        return mmRepoGrant.findByOwnerIdAndSchema(ownerId, schema, Sorts.createTm_asc);
    }

    public List<GeneralGrantEntity> listByOwnerIdAndAction(String ownerId, int action) {
        return mmRepoGrant.findByOwnerIdAndAction(ownerId, action);
    }

    public List<GeneralGrantEntity> findByOwnerIdAndSchemaAndAction(String id, ResourceSchemaEnum menu, int action) {
        return mmRepoGrant.findByOwnerIdAndSchemaAndAction(id, menu, action);
    }

    @Override
    public Page<GeneralGrantEntity> findByKeywords(String keywords, Pageable paging) {

        //TODO 按照关键字查询
        return this.findAll(paging);
    }
}
